﻿using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;
using LuaInterface;
using System.Reflection;
using System.IO;


namespace LuaFramework {
    public class GameManager : Manager {
        protected static bool initialize = false;
        private List<string> downloadFiles = new List<string>();
		private int reLoadCount = 0;//重新加载次数
		private int reCheckFileCount = 0;//检测更新文件次数
        /// <summary>
        /// 初始化游戏管理器
        /// </summary>
        void Awake() {
            Init();
        }
        /// <summary>
        /// 初始化
        /// </summary>
        void Init() {
            DontDestroyOnLoad(gameObject);  //防止销毁自己

            CheckExtractResource(); //释放资源
            Screen.sleepTimeout = SleepTimeout.NeverSleep;
            Application.targetFrameRate = AppConst.GameFrameRate;
        }

        /// <summary>
        /// 释放资源
        /// </summary>
        public void CheckExtractResource() {
			//首先判断加载界面是否存在
			Debug.Log("CheckExtractResource  Util.DataPath = "+Util.DataPath);
			bool loadExists = File.Exists(Util.DataPath+"load/") && File.Exists(Util.DataPath+"load/files.txt");
			if (loadExists || AppConst.DebugMode) {
				StartCoroutine (OnUpdateResource("load"));
				return;
			}
			StartCoroutine (OnExtractResource ("load"));
        }
		/// <summary>
		/// 开始加载游戏主资源
		/// 加载界面资源更新后执行
		/// </summary>
		public void StartLoadMainResource ()
		{
			bool isExists = Directory.Exists (Util.DataPath) && Directory.Exists (Util.DataPath + "lua/") && File.Exists (Util.DataPath + "main/files.txt");
			if (isExists || AppConst.DebugMode) {
				StartCoroutine (OnUpdateResource ("main"));
				return;   //文件已经解压过了，自己可添加检查文件列表逻辑
			}
			StartCoroutine (OnExtractResource ("main"));    //启动释放协成 
		}
			

		IEnumerator OnExtractResource(string _package = "") {
            string dataPath = Util.DataPath;  //数据目录
            string resPath = Util.AppContentPath(); //游戏包资源目录
			if (_package != "") {
				dataPath += _package +"/";
				resPath += _package + "/";
			}

            if (Directory.Exists(dataPath)) Directory.Delete(dataPath, true);
            Directory.CreateDirectory(dataPath);

            string infile = resPath + "files.txt";
            string outfile = dataPath + "files.txt";
            if (File.Exists(outfile)) File.Delete(outfile);

            string message = "正在解包文件:>files.txt";
            Debug.Log(infile);
            Debug.Log(outfile);
            if (Application.platform == RuntimePlatform.Android) {
                WWW www = new WWW(infile);
                yield return www;

                if (www.isDone) {
                    File.WriteAllBytes(outfile, www.bytes);
                }
                yield return 0;
            } else File.Copy(infile, outfile, true);
            yield return new WaitForEndOfFrame();

            //释放所有文件到数据目录
            string[] files = File.ReadAllLines(outfile);
            foreach (var file in files) {
                string[] fs = file.Split('|');
                infile = resPath + fs[0];  //
                outfile = dataPath + fs[0];

                message = "正在解包文件:>" + fs[0];
                Debug.Log("正在解包文件:>" + infile);
                facade.SendMessageCommand(NotiConst.UPDATE_MESSAGE, message);

                string dir = Path.GetDirectoryName(outfile);
                if (!Directory.Exists(dir)) Directory.CreateDirectory(dir);

                if (Application.platform == RuntimePlatform.Android) {
                    WWW www = new WWW(infile);
                    yield return www;

                    if (www.isDone) {
                        File.WriteAllBytes(outfile, www.bytes);
                    }
                    yield return 0;
                } else {
                    if (File.Exists(outfile)) {
                        File.Delete(outfile);
                    }
                    File.Copy(infile, outfile, true);
                }
                yield return new WaitForEndOfFrame();
            }
            message = "解包完成!!!";
            facade.SendMessageCommand(NotiConst.UPDATE_MESSAGE, message);
            yield return new WaitForSeconds(0.1f);

            message = string.Empty;
            //释放完成，开始启动更新资源
            StartCoroutine(OnUpdateResource());
        }
        /// <summary>
        /// 启动更新下载，这里只是个思路演示，此处可启动线程下载更新
        /// </summary>
		IEnumerator OnUpdateResource(string _package="") {
            if (!AppConst.UpdateMode) {
				OnResourceInited(_package);
                yield break;
            }
            string dataPath = Util.DataPath;  //数据目录
			string url = AppConst.WebUrl;
			if (_package != null) {
				dataPath += _package + "/";
				url += _package + "/";
			}
            string message = string.Empty;
            string random = DateTime.Now.ToString("yyyymmddhhmmss");
            string listUrl = url + "files.txt?v=" + random;
            WWW www = new WWW(listUrl); yield return www;
            if (www.error != null) {
				OnUpdateFailed(listUrl,_package);
                yield break;
            }
            if (!Directory.Exists(dataPath)) {
                Directory.CreateDirectory(dataPath);
            }
            File.WriteAllBytes(dataPath + "files.txt", www.bytes);
            string filesText = www.text;
            string[] files = filesText.Split('\n');
			MyDebug.LogRed ("开始检测有多少文件需要更新");
			List<UpdateFileData> updateList = new List<UpdateFileData> ();
            for (int i = 0; i < files.Length; i++) {
                if (string.IsNullOrEmpty(files[i])) continue;
                string[] keyValue = files[i].Split('|');
                string f = keyValue[0];
                string localfile = (dataPath + f).Trim();
                string path = Path.GetDirectoryName(localfile);
                if (!Directory.Exists(path)) {
                    Directory.CreateDirectory(path);
                }
                string fileUrl = url + f + "?v=" + random;
                bool canUpdate = !File.Exists(localfile);
                if (!canUpdate) {
                    string remoteMd5 = keyValue[1].Trim();
                    string localMd5 = Util.md5file(localfile);
                    canUpdate = !remoteMd5.Equals(localMd5);
                    if (canUpdate) File.Delete(localfile);
                }
                if (canUpdate) {   //本地缺少文件
					UpdateFileData temp_data = new UpdateFileData ();
					temp_data.fileUrl = fileUrl;
					temp_data.localFile = localfile;
					updateList.Add (temp_data);
                }
            }
			if(updateList.Count > 0){
				if (_package != "load" && _package != "") {
					Util.CallMethod("CtrlManager","SetTotleUpdate",updateList.Count);
				}
				for (int k = 0; k < updateList.Count; k++) {
//					Debug.Log(fileUrl);
//					message = "downloading>>" + fileUrl;
//					facade.SendMessageCommand(NotiConst.UPDATE_MESSAGE, message);
					//这里都是资源文件，用线程下载
					if (_package != "load" && _package != "") {
						Util.CallMethod("CtrlManager","SetProgress",k);
					}
					reLoadCount = 0;
					BeginDownload(updateList[k].fileUrl, updateList[k].localFile);
					while (!(IsDownOK(updateList[k].localFile))) { yield return new WaitForEndOfFrame(); }
				}
			}
            yield return new WaitForEndOfFrame();
//            message = "更新完成!!";
//            facade.SendMessageCommand(NotiConst.UPDATE_MESSAGE, message);
			OnResourceInited(_package);
        }

		void OnUpdateFailed(string file,string _package) {
//            string message = "更新失败!>" + file;
//            facade.SendMessageCommand(NotiConst.UPDATE_MESSAGE, message);
			MyDebug.LogRed ("验证 更新文件失败 "+file);
			if (reCheckFileCount < 4) {
				reCheckFileCount++;
				StartCoroutine (OnUpdateResource(_package));
			} else {
				MyDebug.LogRed ("验证超过最大次数");
				reCheckFileCount = 0;
			}
        }

        /// <summary>
        /// 是否下载完成
        /// </summary>
        bool IsDownOK(string file) {
            return downloadFiles.Contains(file);
        }

        /// <summary>
        /// 线程下载
        /// </summary>
        void BeginDownload(string url, string file) {     //线程下载
            object[] param = new object[2] { url, file };

            ThreadEvent ev = new ThreadEvent();
            ev.Key = NotiConst.UPDATE_DOWNLOAD;
            ev.evParams.AddRange(param);
            ThreadManager.AddEvent(ev, OnThreadCompleted);   //线程下载
        }

        /// <summary>
        /// 线程完成
        /// </summary>
        /// <param name="data"></param>
        void OnThreadCompleted(NotiData data) {
            switch (data.evName) {
                case NotiConst.UPDATE_EXTRACT:  //解压一个完成
                //
                break;
                case NotiConst.UPDATE_DOWNLOAD: //下载一个完成
                downloadFiles.Add(data.evParam.ToString());
                break;
			case NotiConst.UPDATE_TIMEUP:
				reLoadCount++;
				if (reLoadCount < 4) {
					MyDebug.LogRed ("第 " + reLoadCount + " 次加载  资源 ：" + data.evParam.ToString ());
					BeginDownload (data.evParam.ToString (), data.evParam2.ToString ());
				} else {
					MyDebug.LogRed ("重试次数超过最大值，不再进行加载");
				}
				break;
            }
        }
        /// <summary>
        /// 资源初始化结束
        /// </summary>
		public void OnResourceInited(string _package) {
#if ASYNC_MODE
//			AppConst.AssetDir
			ResManager.Initialize(_package, delegate() {
                Debug.Log("Initialize OK!!!");
				if(_package == "load"){
					this.OnLoadInitialize();
				}
				if(_package == "main"){
					OnInitialize();
				}
            });
#else
            ResManager.Initialize();
			this.OnLoadInitialize();
#endif
			PanelMgr.Init ();
        }


		void OnInitialize(){
			Util.CallMethod("Game", "StartGame");
		}

		void OnLoadInitialize() {
            LuaManager.InitStart();
            LuaManager.DoFile("Logic/Game");         //加载游戏
            LuaManager.DoFile("Logic/Network");      //加载网络
            NetManager.OnInit();                     //初始化网络
            Util.CallMethod("Game", "OnInitOK");     //初始化完成
            initialize = true;
            //类对象池测试
            var classObjPool = ObjPoolManager.CreatePool<TestObjectClass>(OnPoolGetElement, OnPoolPushElement);
            //方法1
            //objPool.Release(new TestObjectClass("abcd", 100, 200f));
            //var testObj1 = objPool.Get();
            //方法2
            ObjPoolManager.Release<TestObjectClass>(new TestObjectClass("abcd", 100, 200f));
//            var testObj1 = ObjPoolManager.Get<TestObjectClass>();
//            Debugger.Log("TestObjectClass--->>>" + testObj1.ToString());
            //游戏对象池测试
//            var prefab = Resources.Load("TestGameObjectPrefab", typeof(GameObject)) as GameObject;
//            var gameObjPool = ObjPoolManager.CreatePool("TestGameObject", 5, 10, prefab);
//
//            var gameObj = Instantiate(prefab) as GameObject;
//            gameObj.name = "TestGameObject_01";
//            gameObj.transform.localScale = Vector3.one;
//            gameObj.transform.localPosition = Vector3.zero;
//
//            ObjPoolManager.Release("TestGameObject", gameObj);
//            var backObj = ObjPoolManager.Get("TestGameObject");
//            backObj.transform.SetParent(null);
//
//            Debug.Log("TestGameObject--->>>" + backObj);
        }

        /// <summary>
        /// 当从池子里面获取时
        /// </summary>
        /// <param name="obj"></param>
        void OnPoolGetElement(TestObjectClass obj) {
            Debug.Log("OnPoolGetElement--->>>" + obj);
        }

        /// <summary>
        /// 当放回池子里面时
        /// </summary>
        /// <param name="obj"></param>
        void OnPoolPushElement(TestObjectClass obj) {
            Debug.Log("OnPoolPushElement--->>>" + obj);
        }

        /// <summary>
        /// 析构函数
        /// </summary>
        void OnDestroy() {
            if (NetManager != null) {
                NetManager.Unload();
            }
            if (LuaManager != null) {
                LuaManager.Close();
            }
            Debug.Log("~GameManager was destroyed");
        }
    }
}